{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-20T10:08:49.063045Z",
     "start_time": "2020-10-20T10:08:48.091607Z"
    }
   },
   "outputs": [],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-20T11:37:58.888471Z",
     "start_time": "2020-10-20T11:37:58.882431Z"
    }
   },
   "outputs": [],
   "source": [
    "batch_size=1\n",
    "seq_len=5\n",
    "\n",
    "input_size=4\n",
    "hidden_size=4\n",
    "num_layers=1\n",
    "\n",
    "cell=torch.nn.RNNCell(input_size=input_size,hidden_size=hidden_size)\n",
    "\n",
    "dataset=torch.randn(seq_len,batch_size,input_size)\n",
    "hidden=torch.zeros(batch_size,hidden_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-20T11:38:00.376788Z",
     "start_time": "2020-10-20T11:38:00.360480Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================== 0 ====================\n",
      "Input size: torch.Size([1, 4])\n",
      "output size: torch.Size([1, 4])\n",
      "tensor([[ 0.6289,  0.2928,  0.3523, -0.2965]], grad_fn=<TanhBackward>)\n",
      "==================== 1 ====================\n",
      "Input size: torch.Size([1, 4])\n",
      "output size: torch.Size([1, 4])\n",
      "tensor([[-0.3434,  0.7171, -0.1316,  0.0134]], grad_fn=<TanhBackward>)\n",
      "==================== 2 ====================\n",
      "Input size: torch.Size([1, 4])\n",
      "output size: torch.Size([1, 4])\n",
      "tensor([[-0.8033,  0.9561,  0.5763, -0.2089]], grad_fn=<TanhBackward>)\n",
      "==================== 3 ====================\n",
      "Input size: torch.Size([1, 4])\n",
      "output size: torch.Size([1, 4])\n",
      "tensor([[-0.7635,  0.9243,  0.0500, -0.6881]], grad_fn=<TanhBackward>)\n",
      "==================== 4 ====================\n",
      "Input size: torch.Size([1, 4])\n",
      "output size: torch.Size([1, 4])\n",
      "tensor([[-0.4517,  0.9297, -0.1904,  0.5775]], grad_fn=<TanhBackward>)\n"
     ]
    }
   ],
   "source": [
    "for idx,input in enumerate(dataset):\n",
    "    print('=' *20 , idx,'='*20)\n",
    "    print('Input size:',input.shape)\n",
    "    \n",
    "    hidden=cell(input,hidden)\n",
    "    print('output size:',hidden.shape)\n",
    "    print(hidden)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-20T11:38:09.111111Z",
     "start_time": "2020-10-20T11:38:09.101532Z"
    }
   },
   "outputs": [],
   "source": [
    "idx2char=['e','h','l','o']\n",
    "x_data=[1,0,2,2,3]\n",
    "y_data=[3,1,2,3,2]\n",
    "\n",
    "one_hot_lookup=[[1,0,0,0],\n",
    "                [0,1,0,0],\n",
    "                [0,0,1,0],\n",
    "                [0,0,0,1]]\n",
    "x_one_hot=[one_hot_lookup[x] for x in x_data]\n",
    "\n",
    "inputs=torch.Tensor(x_one_hot).view(seq_len,batch_size,input_size)\n",
    "labels=torch.LongTensor(y_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-20T11:38:45.194645Z",
     "start_time": "2020-10-20T11:38:45.185124Z"
    }
   },
   "outputs": [],
   "source": [
    "class Model(torch.nn.Module):\n",
    "    def __init__(self,input_size,hidden_size,batch_size,num_layers=1):\n",
    "        super(Model,self).__init__()\n",
    "        self.num_layers=num_layers\n",
    "        self.batch_size=batch_size\n",
    "        self.input_size=input_size\n",
    "        self.hidden_size=hidden_size\n",
    "        self.rnn=torch.nn.RNN(num_layers=self.num_layers,input_size=self.input_size,hidden_size=self.hidden_size)\n",
    "    def forward(self,input):\n",
    "        out,_=self.rnn(input,self.init_hidden())\n",
    "        return out.view(-1,self.hidden_size)\n",
    "    def init_hidden(self):\n",
    "        return torch.zeros(self.num_layers,self.batch_size,self.hidden_size)\n",
    "num_layers=1\n",
    "net=Model(input_size,hidden_size,batch_size,num_layers)\n",
    "    \n",
    "    \n",
    "    \n",
    "    \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-10-20T11:39:04.422874Z",
     "start_time": "2020-10-20T11:39:04.381987Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "predicted:  ohlll ,Epoch [1/15] loss= 0.757\n",
      "predicted:  ohlll ,Epoch [2/15] loss= 0.716\n",
      "predicted:  ohlll ,Epoch [3/15] loss= 0.677\n",
      "predicted:  ohlll ,Epoch [4/15] loss= 0.645\n",
      "predicted:  ohlol ,Epoch [5/15] loss= 0.620\n",
      "predicted:  ohlol ,Epoch [6/15] loss= 0.600\n",
      "predicted:  ohlol ,Epoch [7/15] loss= 0.582\n",
      "predicted:  ohlol ,Epoch [8/15] loss= 0.563\n",
      "predicted:  ohlol ,Epoch [9/15] loss= 0.543\n",
      "predicted:  ohlol ,Epoch [10/15] loss= 0.521\n",
      "predicted:  ohlol ,Epoch [11/15] loss= 0.500\n",
      "predicted:  ohlol ,Epoch [12/15] loss= 0.487\n",
      "predicted:  ohlol ,Epoch [13/15] loss= 0.482\n",
      "predicted:  ohlol ,Epoch [14/15] loss= 0.474\n",
      "predicted:  ohlol ,Epoch [15/15] loss= 0.461\n"
     ]
    }
   ],
   "source": [
    "criterion=torch.nn.CrossEntropyLoss()\n",
    "optimizer=torch.optim.Adam(net.parameters(),lr=0.05)\n",
    "\n",
    "for epoch in range(15):\n",
    "    optimizer.zero_grad()\n",
    "    outputs=net(inputs)\n",
    "    loss=criterion(outputs,labels)\n",
    "    loss.backward()\n",
    "    optimizer.step()\n",
    "    \n",
    "    _,idx=outputs.max(dim=1)\n",
    "    idx=idx.data.numpy()\n",
    "    print('predicted: ',''.join([idx2char[x] for x in idx]),end=' ')\n",
    "    print(',Epoch [%d/15] loss= %.3f'%(epoch +1,loss.item()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
